channel 是goroutine的通道,所以不能直接在非goroutine里直接进行操作,否则会报错,例如
1 | c := make(chan int) |
var i chan int // 双向channel
var i chan<- int // 单向,只能收数据
i <- 1 // 这是允许的
j <- i // 这是不允许的
var i <-chan int // 单向,只能发数据
buffer channel
buffer可以减少goroutine的切换,例如下面,创建了3buffer的channel,在往channel写数据时,前3个写入都是会存储到buffer,但是写第4个的时候,会发现报错,fatal error: all goroutines are asleep - deadlock!
,因为buffer已满,没有goroutine处理该channel数据。所以如果是没有buffer的channel,每次写入都会有一次goroutine的切换。
1 | func bufferChannel() { |
channel close
1 | func worker(c chan int) { |
不要通过共享内存来通信,通过通信来共享内存
这篇文章里面说的比较清楚了,使用共享内存的话在多线程的场景下为了处理竞态,需要加锁,使用起来比较麻烦。另外使用过多的锁,容易使得程序的代码逻辑坚涩难懂,并且容易使程序死锁,死锁了以后排查问题相当困难,特别是很多锁同时存在的时候。
go语言的channel保证同一个时间只有一个goroutine能够访问里面的数据,为开发者提供了一种优雅简单的工具,所以go原生的做法就是使用channle来通信,而不是使用共享内存来通信。
http://legendtkl.com/2017/07/30/understanding-golang-channel/